<?php
namespace core;
class Async 
{
	static function request($url, $method = 'GET', $postfields = NULL, $headers = array()) {
			$parse = parse_url($url);
			isset($parse['host']) ||$parse['host'] = '';
			isset($parse['path']) || $parse['path'] = '';
			isset($parse['query']) || $parse['query'] = '';
			isset($parse['port']) || $parse['port'] = '';
			$path = $parse['path'] ? $parse['path'].($parse['query'] ? '?'.$parse['query'] : '') : '/';
			$host = $parse['host'];
			//协议
			if ($parse['scheme'] == 'https') {
				$version = '1.1';
				$port = empty($parse['port']) ? 443 : $parse['port'];
				$host = 'ssl://'.$host;
			} else {
				$version = '1.0';
				$port = empty($parse['port']) ? 80 : $parse['port'];
			}
			//Headers
			$headers[] = "Host: {$parse['host']}";
			$headers[] = 'Connection: Close';
			$headers[] = "User-Agent: $_SERVER[HTTP_USER_AGENT]";  
			$headers[] = 'Accept: */*';
			//包体信息
			if ($method == 'POST') {
				if(is_array($postfields)){
					$postfields = http_build_query($postfields);
				}
				$headers[] = "Content-type: application/x-www-form-urlencoded";
				$headers[] = 'Content-Length: '.strlen($postfields);
				$out = "POST $path HTTP/$version\r\n".join("\r\n", $headers)."\r\n\r\n".$postfields;
			} else {
				$out = "GET $path HTTP/$version\r\n".join("\r\n", $headers)."\r\n\r\n";
			}
			//发送请求
			$limit = 0;
			$fp = fsockopen($host, $port, $errno, $errstr, 30);
			if (!$fp) {
				exit('Failed to establish socket connection: '.$url);
			} else {
				$header = $content = '';
				//集阻塞/非阻塞模式流,$block==true则应用流模式
				stream_set_blocking($fp, true);
				//设置流的超时时间
				stream_set_timeout($fp, 30);
				fwrite($fp, $out);
				//从封装协议文件指针中取得报头／元数据
				$status = stream_get_meta_data($fp);
				if (!$status['timed_out']) { //未超时
					while (!feof($fp)) {
						$header .= $h = fgets($fp);
						if ($h && ($h == "\r\n" ||  $h == "\n")) break;
						if (strpos($h, 'Content-Length:') !== false) {
							$limit = intval(substr($header, 15));
						}
					}
					$stop = false;
					while (!feof($fp) && !$stop) {
						$data = fread($fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit));
						$content .= $data;
						if ($limit) {
							$limit -= strlen($data);
							$stop = $limit <= 0;
						}
					}
				}
				fclose($fp);
				//unchunk
				$content = preg_replace_callback(
					'/(?:(?:\r\n|\n)|^)([0-9A-F]+)(?:\r\n|\n){1,2}(.*?)'.
					'((?:\r\n|\n)(?:[0-9A-F]+(?:\r\n|\n))|$)/si',
					create_function(
						'$matches',
						'return hexdec($matches[1]) == strlen($matches[2]) ? $matches[2] : $matches[0];'
					),
					$content
				);
				return $content;
			}
	}
}